package com.study.www.config;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.RandomStringUtils;
import org.springframework.beans.propertyeditors.CustomDateEditor;
import org.springframework.http.HttpStatus;
import org.springframework.ui.Model;
import org.springframework.validation.BindException;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.*;

import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Iterator;
import java.util.Set;

/**
 * @author : THINK.zhuyanpeng
 * @Description: : 全局异常捕获
 * @date :Create in  2019/2/5- 18:04
 * @Version: V1.0
 * @Modified By:
 **/
@Slf4j
@ControllerAdvice
public class WebAdvice {

    public static  final String ID="id";

    public static final SimpleDateFormat DATEFORMAT = new SimpleDateFormat("yyyyMMddHHmmss");
    /**
     * 应用到所有@RequestMapping注解方法，在其执行之前初始化数据绑定器
     * @param binder
     */
    @InitBinder
    public void initWebBinder(WebDataBinder binder){
        //对日期的统一处理
        CustomDateEditor customDateEditor = new CustomDateEditor(DATEFORMAT,true);
        //注册时间编辑器解决前后台时间传参的问题
        binder.registerCustomEditor(Date.class,customDateEditor);
    }

    /**
     * 把值绑定到Model中，使全局 Model 可以获取到该值
     * @param model
     */
    @ModelAttribute
    public void addAttribute(Model model) {
        String id = RandomStringUtils.randomAlphanumeric(10);
        model.addAttribute(ID,  id);
    }


    @ExceptionHandler(ConstraintViolationException.class)
    @ResponseStatus(value = HttpStatus.INTERNAL_SERVER_ERROR)
    @ResponseBody
    public Result constraintViolationException(ConstraintViolationException  e){
        log.info(" ============= ConstraintViolationException =============");
        Set<ConstraintViolation<?>> constraintViolations = e.getConstraintViolations();
        if (constraintViolations.size() > 0){
            Iterator<ConstraintViolation<?>> iterator = constraintViolations.iterator();
            while (iterator.hasNext()){
                ConstraintViolation<?> next = iterator.next();
                return Result.error(next.getMessage());
            }
        }
        return Result.error();
    }

    @ExceptionHandler(BindException.class)
    @ResponseStatus(value = HttpStatus.INTERNAL_SERVER_ERROR)
    @ResponseBody
    public Result bindException(BindException  e){
        FieldError fieldError = e.getBindingResult().getFieldError();
        log.info(" ============= BindException =============");
        return  Result.error(fieldError.getDefaultMessage());
    }

    @ExceptionHandler(MethodArgumentNotValidException.class)
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    @ResponseBody
    public Result notValid(MethodArgumentNotValidException e) {
        BindingResult result = e.getBindingResult();
        log.info(" ============= MethodArgumentNotValidException =============");
        String s = result.getFieldError().getDefaultMessage();
        return Result.error(s);
    }
}
